package com.codi.api.controller;

import com.alibaba.fastjson.JSON;
import com.codi.api.security.UserUtil;
import com.codi.api.validation.QueryValidation;
import com.codi.base.exception.BaseAppException;
import com.codi.base.log.annotation.Loggable;
import com.codi.base.util.EqualsUtil;
import com.codi.base.util.ExceptionUtil;
import com.codi.base.util.StringUtil;
import com.codi.base.web.ResponseUtils;
import com.codi.bus.constant.GlobalConstant;
import com.codi.bus.constant.RuleConstant;
import com.codi.bus.core.domain.Lookup;
import com.codi.bus.core.domain.User;
import com.codi.bus.core.resultModel.*;
import com.codi.bus.core.service.*;
import com.codi.bus.core.service.model.BankModel;
import com.codi.bus.core.service.model.ShareTypeModel;
import com.codi.bus.core.service.model.T0Model;
import com.codi.bus.exception.BaseException;
import com.codi.message.constant.ErrorConst;
import com.codi.message.constant.ErrorConstant;
import com.codi.message.util.MessageUtil;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/query")
public class QueryController {

    private static final Logger logger = LoggerFactory.getLogger(QueryController.class);

    @Resource(name = "userService")
    private UserService userService;

    @Resource(name = "queryService")
    private QueryService queryService;

    @Resource(name = "fundInfoService")
    private FundInfoService fundInfoService;

    @Resource(name = "lookupService")
    private LookupService lookupService;

    @Autowired
    private QueryValidation queryValidation;

    @Autowired
    private T0Service t0Service;

    @Loggable
    @RequestMapping(value = "/assets", method = RequestMethod.GET)
    @ResponseBody
    public BaseResult assetsQuery(HttpServletRequest request, HttpServletResponse response, @RequestParam String token,
                                  @RequestHeader(value = GlobalConstant.HEADER_APP_DEVICE) String deviceId) {

        AssetsResult result = null;
        // 验证token
        ValidateTokenResult validateTokenResult = userService.validateToken(token, deviceId);
        if (!validateTokenResult.getSuccess()) {
            String errorMessage = MessageUtil.getErrorMessage(validateTokenResult.getErrorCode(), null);
            validateTokenResult.setErrorMessage(errorMessage);

            return validateTokenResult;
        }

        result = queryService.queryAssets(validateTokenResult.getUserId());
        if (result.getSuccess() == false && StringUtil.isEmpty(result.getErrorMessage())) {
            result.setErrorMessage(MessageUtil.getErrorMessage(result.getErrorCode(), null));
        }

        return result;
    }

    @Loggable
    @RequestMapping(value = "/limits", method = RequestMethod.GET)
    public void limitQuery(HttpServletRequest request, HttpServletResponse response,
                           @RequestParam String token,
                           @RequestParam String fundCode,
                           @RequestParam String capitalMode,
                           @RequestParam String businCode,
                           @RequestHeader(value = GlobalConstant.HEADER_APP_DEVICE) String deviceId) {
        TradeLimitListResult result = new TradeLimitListResult();
        // 验证token
        ValidateTokenResult validateTokenResult = userService.validateToken(token, deviceId);
        if (!validateTokenResult.getSuccess()) {
            String errorMessage = MessageUtil.getErrorMessage(validateTokenResult.getErrorCode(), null);
            validateTokenResult.setErrorMessage(errorMessage);
            ResponseUtils.renderJson(request, response, validateTokenResult, true);
            return;
        }

        ShareTypeModel shareTypeModel = queryService.getShareType(fundCode);
        if (shareTypeModel == null || StringUtil.isEmpty(shareTypeModel.getShareType())) {
            logger.info("limitQuery - fundCode:{}, can not find share type", fundCode);
            result.setSuccess(false);
            result.setErrorCode(ErrorConstant.ERROR_NO_SHARE_TYPE_FIND);
            result.setErrorMessage(MessageUtil.getErrorMessage(ErrorConstant.ERROR_NO_SHARE_TYPE_FIND, null));
            ResponseUtils.renderJson(request, response, result, true);
            return;
        }

        String shareType = shareTypeModel.getShareType();
        logger.info("limitQuery - fundCode:{}, shareType={}", fundCode, shareType);

        User user = userService.getUser(validateTokenResult.getUserId());

        String custType = user.getIsOrg() ? GlobalConstant.CUST_TYPE_ORGANIZATION : GlobalConstant.CUST_TYPE_PERSONAL;


        result = queryService.queryTradeLimits(GlobalConstant.MAX_REQUEST_NUM, 1, 1, "1", fundCode, shareType,
            capitalMode, businCode, custType);
        if (result.getSuccess() == false && StringUtil.isEmpty(result.getErrorMessage())) {
            result.setErrorMessage(MessageUtil.getErrorMessage(result.getErrorCode(), null));
        }

        logger.info("limitQuery - fundCode:{}, shareType={}, result={}", fundCode, shareType, result);
        ResponseUtils.renderJson(request, response, result, true);
    }

    @Loggable
    @RequestMapping(value = "/accbank", method = RequestMethod.GET)
    public void accountBankQuery(HttpServletRequest request, HttpServletResponse response, @RequestParam String token,
                                 @RequestParam String tradeAccount,
                                 @RequestHeader(value = GlobalConstant.HEADER_APP_DEVICE) String deviceId) {
        BankResult result = new BankResult();
        logger.info("accountBankQuery - tradeAccount:" + tradeAccount);
        // 验证token
        ValidateTokenResult validateTokenResult = userService.validateToken(token, deviceId);
        if (!validateTokenResult.getSuccess()) {
            String errorMessage = MessageUtil.getErrorMessage(validateTokenResult.getErrorCode(), null);
            validateTokenResult.setErrorMessage(errorMessage);
            ResponseUtils.renderJson(request, response, validateTokenResult, true);
            return;
        }

        if (StringUtil.isEmpty(tradeAccount)) {
            result.setSuccess(false);
            result.setErrorCode(ErrorConstant.ERROR_FIELD_NO_FIND);
            Map<String, String> map = new HashMap<>();
            map.put(ErrorConstant.PLACEHOLDER_FIELD_NO_FIND_FIELD, "交易账号");
            result.setErrorMessage(MessageUtil.getErrorMessage(ErrorConstant.ERROR_FIELD_NO_FIND, map));

            ResponseUtils.renderJson(request, response, result, true);
            return;
        }

        BaseListResult listResult = queryService.queryAccountBanks(tradeAccount, "", "", 1, 1, 1, "");
        if (!listResult.getSuccess()) {
            ResponseUtils.renderJson(request, response, listResult, true);
            return;
        }
        result.setSuccess(true);
        List<BankModel> banks = ((BankListResult) listResult).getBanks();
        if (banks != null && banks.size() > 0) {
            BankModel model = banks.get(0);
            result.setBankName(model.getBankName());
        }
        ResponseUtils.renderJson(request, response, result, true);

    }

    @Loggable
    @RequestMapping(value = "/sharetype", method = RequestMethod.GET)
    public void shareTypeQuery(HttpServletRequest request, HttpServletResponse response,
                               @RequestParam String fundCode) {
        ShareTypeResult result = new ShareTypeResult();
        if (StringUtil.isEmpty(fundCode)) {
            result.setSuccess(false);
            result.setErrorCode(ErrorConstant.ERROR_FIELD_NO_FIND);
            Map<String, String> map = new HashMap<>();
            map.put(ErrorConstant.PLACEHOLDER_FIELD_NO_FIND_FIELD, "基金");
            result.setErrorMessage(MessageUtil.getErrorMessage(ErrorConstant.ERROR_FIELD_NO_FIND, map));
        } else {
            result.setSuccess(true);

            ShareTypeListResult  listResult = queryService.queryShareTypes(1, 1, 1, "", fundCode, "");
            List<ShareTypeModel> shareTypes = listResult.getShareTypes();
            if (shareTypes != null && shareTypes.size() > 0) {
                ShareTypeModel model = shareTypes.get(0);
                result.setFundCode(model.getFundCode());
                result.setFundName(model.getFundName());
                result.setShareType(model.getShareType());
            }
        }
        ResponseUtils.renderJson(request, response, result, true);
    }

    @Loggable
    @Deprecated // 参考v2.QueryControllerV2  shi.pengyan 2017-9-26 14:21:07
    @RequestMapping(value = "/applys", method = RequestMethod.GET)
    public void applyQuery(HttpServletRequest request, HttpServletResponse response, @RequestParam String token,
                           @RequestParam Integer requestNum, @RequestParam Integer queryFlag, @RequestParam Integer beginNum,
                           @RequestParam String sortDirection,
                           @RequestHeader(value = GlobalConstant.HEADER_APP_DEVICE) String deviceId) {
        ApplyListResult result = null;
        // 验证token
        ValidateTokenResult validateTokenResult = userService.validateToken(token, deviceId);
        if (!validateTokenResult.getSuccess()) {
            String errorMessage = MessageUtil.getErrorMessage(validateTokenResult.getErrorCode(), null);
            validateTokenResult.setErrorMessage(errorMessage);
            ResponseUtils.renderJson(request, response, validateTokenResult, true);
            return;
        }

        result = queryService.queryApplys(validateTokenResult.getUserId(), requestNum, queryFlag, beginNum,
            sortDirection, false);
        if (result.getSuccess() == false && StringUtil.isEmpty(result.getErrorMessage())) {
            result.setErrorMessage(MessageUtil.getErrorMessage(result.getErrorCode(), null));
        }
        ResponseUtils.renderJson(request, response, result, true);
    }

    @Loggable
    @RequestMapping(value = "/funds", method = RequestMethod.GET)
    public void fundQuery(HttpServletRequest request, HttpServletResponse response, @RequestParam Integer requestNum,
                          @RequestParam Integer queryFlag, @RequestParam Integer beginNum, @RequestParam String sortDirection,
                          @RequestParam String fundCode) {
        FundListResult result = null;
        result = queryService.queryFunds(requestNum, queryFlag, beginNum, sortDirection, fundCode);
        if (result.getSuccess() == false && StringUtil.isEmpty(result.getErrorMessage())) {
            result.setErrorMessage(MessageUtil.getErrorMessage(result.getErrorCode(), null));
        }
        ResponseUtils.renderJson(request, response, result, true);
    }

    @Loggable
    @Deprecated // 参考v2.QueryControllerV2  shi.pengyan 2017-9-26 14:21:33
    @RequestMapping(value = "/shares", method = RequestMethod.GET)
    public void shareQuery(HttpServletRequest request, HttpServletResponse response, @RequestParam String token,
                           @RequestParam Integer requestNum, @RequestParam Integer queryFlag, @RequestParam Integer beginNum,
                           @RequestParam String sortDirection,
                           @RequestHeader(value = GlobalConstant.HEADER_APP_DEVICE) String deviceId) {

        ShareListResult result = null;
        // 验证token
        ValidateTokenResult validateTokenResult = userService.validateToken(token, deviceId);
        if (!validateTokenResult.getSuccess()) {
            String errorMessage = MessageUtil.getErrorMessage(validateTokenResult.getErrorCode(), null);
            validateTokenResult.setErrorMessage(errorMessage);
            ResponseUtils.renderJson(request, response, validateTokenResult, true);
            return;
        }

        // 验证输入
        result = queryValidation.validateShareQuery(requestNum);
        if (result != null) {
            ResponseUtils.renderJson(request, response, result, true);
            return;
        }
        //zx 2018-1-4 11:46:38
        result = queryService.querySharesWithoutPort(validateTokenResult.getUserId(), requestNum, queryFlag, beginNum,
            //result = queryService.queryShares(validateTokenResult.getUserId(), requestNum, queryFlag, beginNum,
            sortDirection, false);
        if (result.getSuccess() == false && StringUtil.isEmpty(result.getErrorMessage())) {
            result.setErrorMessage(MessageUtil.getErrorMessage(result.getErrorCode(), null));
        }
        ResponseUtils.renderJson(request, response, result, true);
    }

    /**
     * 查询基金基本信息
     *
     * @param request
     * @param response
     * @param keyword
     * @throws Exception
     */
    @Loggable
    @Deprecated // 参考v2.QueryControllerV2 shi.pengyan 2017-9-26 14:22:14
    @RequestMapping("/fundInfos")
    @ResponseBody
    public void queryFundInfo(HttpServletRequest request, HttpServletResponse response, @RequestParam String keyword) {
        FundInfoListResult result = null;
        try {

            // 查询基金
            result = fundInfoService.query(keyword, UserUtil.getLoginUserId());

        } catch (BaseException exception) {
            result = new FundInfoListResult();
            result.setSuccess(false);
            Integer errorCode = exception.getCode();
            result.setErrorCode(errorCode);
            if (StringUtil.isEmpty(result.getErrorMessage())) {
                String errorMessage = MessageUtil.getErrorMessage(errorCode, null);
                result.setErrorMessage(errorMessage);
            }
        } catch (Exception e) {
            ExceptionUtil.logError(logger, "queryFundInfo - Exception:", e);
            result = new FundInfoListResult();
            result.setSuccess(false);
            result.setErrorCode(ErrorConstant.ERROR_SYS_EXCEPTION);
            result.setErrorMessage(MessageUtil.getErrorMessage(ErrorConstant.ERROR_SYS_EXCEPTION, null));
        }

        ResponseUtils.renderJson(request, response, result, true);
    }

    /**
     * 定投基金查询
     *
     * @param request
     * @param response
     * @param token         用户TOKEN
     * @param requestNum    请求行数
     * @param queryFlag     重新统计总记录数标志
     * @param beginNum      查询起始行号
     * @param sortDirection 返回排序方式 （0:倒序；1：顺序）
     */
    @RequestMapping(value = "fixes", method = RequestMethod.GET)
    @Loggable
    public
    @ResponseBody
    FixListResult fixes(HttpServletRequest request, HttpServletResponse response, @RequestParam String token,
                        @RequestParam Integer requestNum, @RequestParam Integer queryFlag, @RequestParam Integer beginNum,
                        @RequestParam String sortDirection,
                        @RequestHeader(value = GlobalConstant.HEADER_APP_DEVICE) String deviceId) {
        FixListResult result = null;
        // 验证token
        ValidateTokenResult validateTokenResult = userService.validateToken(token, deviceId);
        if (!validateTokenResult.getSuccess()) {
            String errorMessage = MessageUtil.getErrorMessage(validateTokenResult.getErrorCode(), null);
            validateTokenResult.setErrorMessage(errorMessage);
            ResponseUtils.renderJson(request, response, validateTokenResult, true);
            return result;
        }

        // 查询定投基金
        return queryService.getFixes(validateTokenResult.getUserId(), requestNum, queryFlag, beginNum, sortDirection);

    }


    /**
     * 查询 科地瑞富的收款账户
     *
     * @return
     */
    @Loggable
    @RequestMapping(value = "codi_ruifu_bank_info", method = RequestMethod.GET)
    @ResponseBody
    public com.codi.base.domain.BaseResult getCodiRuifuBankInfo() throws BaseAppException {

        Lookup lookup = lookupService.getLookup("SYSTEM", "CODI_RUIFU_BANK_INFO");

        if (lookup == null) {
            logger.error("请检查脚本 SYSTEM:CODI_RUIFU_BANK_INFO");
            com.codi.base.exception.ExceptionHandler.publish(ErrorConst.COMMON_SYSTEM_ERROR);
        }

        return new com.codi.base.domain.BaseResult(JSON.parseObject(lookup.getComponentValue()));
    }


    /**
     * 查询利率最高的t0 首页推荐瑞福宝
     *
     * @return
     */
    @Loggable
    @GetMapping("/top_rate_t0_fund")
    @ResponseBody
    public BaseResult getTopRateT0() {
        boolean isOrg = false;

        Long userId = UserUtil.getLoginUserIdIfNeed();
        if (userId != null) {
            User user = userService.getUser(userId);
            if (user.getIsOrg()) {
                isOrg = true;
            }
        }

        BaseResult result = new BaseResult();

        T0Model model;

        Lookup lookup = lookupService.getLookup(RuleConstant.APP_HOME_DISPLAY_T0);
        if (EqualsUtil.equals(1, lookup.getRuleStatus().intValue())) { // 使用自定义
            model = t0Service.queryT0Fund(isOrg, lookup.getRuleValue());
        } else { // 不是用自定义
            model = t0Service.queryTopRateFund(isOrg);
        }

        return result.setSuccess(true).setResult(model);
    }

    /**
     * t0 列表
     *
     * @return
     */
    @Loggable
    @GetMapping("/t0_funds")
    @ResponseBody
    public BaseResult getT0List() {
        boolean isOrg = false;

        Long userId = UserUtil.getLoginUserIdIfNeed();
        if (userId != null) {
            User user = userService.getUser(userId);
            if (user.getIsOrg()) {
                isOrg = true;
            }
        }


        Lookup lookup = lookupService.getLookup(RuleConstant.T0FUND_LIST_DISPLAY_FUNDS);

        List<T0Model> data;

        if (EqualsUtil.equals(1, lookup.getRuleStatus().intValue())) { // 使用
            String   valueStr      = lookup.getRuleValue();
            String[] fundCodeArray = valueStr.split(",");

            data = t0Service.queryT0Funds(isOrg, Arrays.asList(fundCodeArray));
        } else { // 不是用
            data = t0Service.queryT0Funds(isOrg);
        }


        BaseResult result = new BaseResult();

        return result.setSuccess(true).setResult(data);
    }

    /**
     * 查询t0列表降序--区分收益结算方式
     * @param fundReport 基金结算方式 R：收益日结转 Y：收益月结转
     * @return
     */
    @Loggable
    @GetMapping("/t0_funds_report")
    @ResponseBody
    public BaseResult getT0ReportList(@RequestParam String fundReport) {
        BaseResult result = new BaseResult();
        if(!"R".equals(fundReport) && !"Y".equals(fundReport)){
            result.setSuccess(false);
            result.setErrorCode(ErrorConstant.ERROR_FIELD_NO_FIND);
            result.setErrorType(GlobalConstant.ERROR_TYPE_BUSINESS);
            result.setErrorMessage("参数错误");
            return result;
        }

        boolean isOrg = false;

        Long userId = UserUtil.getLoginUserIdIfNeed();
        if (userId != null) {
            User user = userService.getUser(userId);
            if (user.getIsOrg()) {
                isOrg = true;
            }
        }
        Lookup lookup = lookupService.getLookup(RuleConstant.T0FUND_LIST_DISPLAY_FUNDS);

        List<T0Model> data;

        if (EqualsUtil.equals(1, lookup.getRuleStatus().intValue())) { // 使用
            String   valueStr      = lookup.getRuleValue();
            String[] fundCodeArray = valueStr.split(",");

            data = t0Service.queryT0Funds(isOrg, Arrays.asList(fundCodeArray));
        } else { // 不是用
            data = t0Service.queryT0Funds(isOrg);
        }
        List<T0Model> returnList = Lists.newArrayList();
        for(T0Model model:data){
            if(fundReport.equals(model.getFundReport())){
                returnList.add(model);
            }
        }
        return result.setSuccess(true).setResult(returnList);
    }

}
